/*
 * ControladorR11B.h
 *
 *  Created on: Nov 19, 2013
 *      Author: m
 */

#ifndef CONTROLADORR11B_H_
#define CONTROLADORR11B_H_

#include "DefinicionesComunes.h"
#include "ICinta13B.h"
#include "IRobot11B.h"
#include "IRobot14.h"

#include "Cinta13B.h"
#include "Robot11BProductor.h"
#include "Robot14Consumidor.h"
#include "DSMManager.h"

class ControladorR11B :
        public ICinta13B, public IRobot11B, public IRobot14
{
protected:
    Cinta13B m_cinta13B;
    Robot11BProductor m_robot11B;
    Robot14Consumidor m_robot14;
    bool m_tomarCinta;

public:

    ControladorR11B() :
        m_cinta13B(),
        m_robot11B(),
        m_tomarCinta( true )
    {
        DSMManager::inicializar("robot11b");
    }

    virtual ~ControladorR11B()
    {
    }

    bool c13b_depositar( const ElementoProduccion &e )
    {
        bool depositoOk;

        m_cinta13B.iniciarExclusionMutua();

        if ( m_tomarCinta )
        {
            m_tomarCinta = false;


            // Antes de utilizar la cinta debo verificar que no la este
            //  usando el otro robot. En ese caso me quedo esperando que
            //  termine de usarla.

            if ( m_cinta13B.getCinta()->consumidorUsando() )
            {
                m_cinta13B.getCinta()->setProductorEsperando( true );

                m_cinta13B.terminarExclusionMutua();

                m_cinta13B.dormirProductor();

                m_cinta13B.iniciarExclusionMutua();
            }

            m_cinta13B.getCinta()->setProductorUsando( true );
        }

        depositoOk = m_cinta13B.getCinta()->depositar( e );

        m_cinta13B.terminarExclusionMutua();

        return depositoOk;
    }

    bool c13b_avanzar()
    {
        bool avanzoOk;

        m_cinta13B.iniciarExclusionMutua();

        avanzoOk = m_cinta13B.getCinta()->avanzar();

        m_cinta13B.terminarExclusionMutua();

        return avanzoOk;
    }

    void r11b_esperarEspacioVacio()
    {
        // Actualizo el estado del robot11

        m_robot11B.iniciarExclusionMutua();

        m_robot11B.setEsperaEspacio( true );

        m_robot11B.terminarExclusionMutua();

        // Libero la cinta
        m_tomarCinta = true;

        m_cinta13B.iniciarExclusionMutua();

        m_cinta13B.getCinta()->setProductorUsando( false );

        // Reviso si el consumidor estaba esperando, si es asi lo despierto

        if ( m_cinta13B.getCinta()->consumidorEsperando() )
        {
            m_cinta13B.getCinta()->setConsumidorEsperando( false );

            m_cinta13B.getCinta()->setConsumidorUsando( true );

            m_cinta13B.despertarConsumidor();
        }

        m_cinta13B.terminarExclusionMutua();

        // Duermo
        m_robot11B.dormir();
    }

    void r14_notificarNuevoElemento()
    {
        bool esperaProducto;

        m_robot14.iniciarExclusionMutua();

        if ( m_robot14.esperaProducto() )
        {
            m_robot14.setEsperaProducto( false );

            m_robot14.despertar();
        }

        m_robot14.terminarExclusionMutua();


        // Indico que ya no voy a utilizar más la cinta

        m_cinta13B.iniciarExclusionMutua();

        m_cinta13B.getCinta()->setProductorUsando( false );

        // Reviso si el consumidor estaba esperando, si es asi lo despierto

        if ( m_cinta13B.getCinta()->consumidorEsperando() )
        {
            m_cinta13B.getCinta()->setConsumidorEsperando( false );

            m_cinta13B.getCinta()->setConsumidorUsando( true );

            m_cinta13B.despertarConsumidor();
        }

        m_cinta13B.terminarExclusionMutua();
    }







    int c13b_contarElementos()
    {
        throw Exception("Metodo no implementado");
    }

    bool c13b_tieneElementos()
    {
        throw Exception("Metodo no implementado");
    }

    ElementoProduccion c13b_quitar()
    {
        throw Exception("Metodo no implementado");
    }

    bool r11b_esperaEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r11b_notificarEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r11b_notificarQuiteElemento()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_esperarNuevoElemento()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_esperarEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    bool r14_esperaEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_notificarEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_notificarQuiteElemento()
    {
        throw Exception("Metodo no implementado");
    }
};

#endif /* CONTROLADORR11B_H_ */
